home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / examples / dinospin.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  10KB  |  353 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994.  */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. /* New GLUT 3.0 glutGetModifiers() functionality used to make Shift-Left
  9.    mouse scale the dinosaur's size. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <math.h>       /* for cos(), sin(), and sqrt() */
  15. #include <GL/glu.h>
  16. #include <GL/glut.h>
  17. #include "trackball.h"
  18.  
  19. typedef enum {
  20.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  21.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  22. } displayLists;
  23.  
  24. GLfloat angle = -150;   /* in degrees */
  25. GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE;
  26. int spinning = 0, moving = 0;
  27. int beginx, beginy;
  28. int W = 300, H = 300;
  29. float curquat[4];
  30. float lastquat[4];
  31. GLdouble bodyWidth = 2.0;
  32. int newModel = 1;
  33. int scaling;
  34. float scalefactor = 1.0;
  35.  
  36. /* *INDENT-OFF* */
  37. GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  38.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  39.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  40.   {1, 2} };
  41. GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  42.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  43.   {13, 9}, {11, 11}, {9, 11} };
  44. GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  45.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  46. GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  47.   {9.6, 15.25}, {9, 15.25} };
  48. GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0};
  49. GLfloat lightZeroColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  50. GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0};
  51. GLfloat lightOneColor[] = {0.6, 0.3, 0.2, 1.0}; /* red-tinted */
  52. GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  53. /* *INDENT-ON* */
  54.  
  55. void
  56. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  57.   GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
  58. {
  59.   static GLUtriangulatorObj *tobj = NULL;
  60.   GLdouble vertex[3], dx, dy, len;
  61.   int i;
  62.   int count = dataSize / (2 * sizeof(GLfloat));
  63.  
  64.   if (tobj == NULL) {
  65.     tobj = gluNewTess();  /* create and initialize a GLU
  66.                              polygon * * tesselation object */
  67.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  68.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky 
  69.                                                       */
  70.     gluTessCallback(tobj, GLU_END, glEnd);
  71.   }
  72.   glNewList(side, GL_COMPILE);
  73.   glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
  74.                                tessellation */
  75.   gluBeginPolygon(tobj);
  76.   for (i = 0; i < count; i++) {
  77.     vertex[0] = data[i][0];
  78.     vertex[1] = data[i][1];
  79.     vertex[2] = 0;
  80.     gluTessVertex(tobj, vertex, data[i]);
  81.   }
  82.   gluEndPolygon(tobj);
  83.   glEndList();
  84.   glNewList(edge, GL_COMPILE);
  85.   glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
  86.                              from being * * "smoothed" */
  87.   glBegin(GL_QUAD_STRIP);
  88.   for (i = 0; i <= count; i++) {
  89.     /* mod function handles closing the edge */
  90.     glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  91.     glVertex3f(data[i % count][0], data[i % count][1], thickness);
  92.     /* Calculate a unit normal by dividing by Euclidean
  93.        distance. We * could be lazy and use
  94.        glEnable(GL_NORMALIZE) so we could pass in * arbitrary
  95.        normals for a very slight performance hit. */
  96.     dx = data[(i + 1) % count][1] - data[i % count][1];
  97.     dy = data[i % count][0] - data[(i + 1) % count][0];
  98.     len = sqrt(dx * dx + dy * dy);
  99.     glNormal3f(dx / len, dy / len, 0.0);
  100.   }
  101.   glEnd();
  102.   glEndList();
  103.   glNewList(whole, GL_COMPILE);
  104.   glFrontFace(GL_CW);
  105.   glCallList(edge);
  106.   glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  107.   glCallList(side);
  108.   glPushMatrix();
  109.   glTranslatef(0.0, 0.0, thickness);
  110.   glFrontFace(GL_CCW);
  111.   glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side 
  112.                                */
  113.   glCallList(side);
  114.   glPopMatrix();
  115.   glEndList();
  116. }
  117.  
  118. void
  119. makeDinosaur(void)
  120. {
  121.   GLfloat bodyWidth = 3.0;
  122.  
  123.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  124.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  125.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  126.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  127.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  128.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  129.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  130.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  131.   glNewList(DINOSAUR, GL_COMPILE);
  132.   glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  133.   glCallList(BODY_WHOLE);
  134.   glPushMatrix();
  135.   glTranslatef(0.0, 0.0, bodyWidth);
  136.   glCallList(ARM_WHOLE);
  137.   glCallList(LEG_WHOLE);
  138.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  139.   glCallList(ARM_WHOLE);
  140.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  141.   glCallList(LEG_WHOLE);
  142.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  143.   glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  144.   glCallList(EYE_WHOLE);
  145.   glPopMatrix();
  146.   glEndList();
  147. }
  148.  
  149. void
  150. recalcModelView(void)
  151. {
  152.   GLfloat m[4][4];
  153.  
  154.   glPopMatrix();
  155.   glPushMatrix();
  156.   build_rotmatrix(m, curquat);
  157.   glMultMatrixf(&m[0][0]);
  158.   glScalef(scalefactor, scalefactor, scalefactor);
  159.   glTranslatef(-8, -8, -bodyWidth / 2);
  160.   newModel = 0;
  161. }
  162.  
  163. void
  164. showMessage(GLfloat x, GLfloat y, GLfloat z, char *message)
  165. {
  166.   glPushMatrix();
  167.   glDisable(GL_LIGHTING);
  168.   glTranslatef(x, y, z);
  169.   glScalef(.02, .02, .02);
  170.   while (*message) {
  171.     glutStrokeCharacter(GLUT_STROKE_ROMAN, *message);
  172.     message++;
  173.   }
  174.   glEnable(GL_LIGHTING);
  175.   glPopMatrix();
  176. }
  177.  
  178. void
  179. redraw(void)
  180. {
  181.   if (newModel)
  182.     recalcModelView();
  183.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  184.   glCallList(DINOSAUR);
  185.   showMessage(2, 7.1, 4.1, "Spin me.");
  186.   glutSwapBuffers();
  187. }
  188.  
  189. void
  190. myReshape(int w, int h)
  191. {
  192.   glViewport(0, 0, w, h);
  193.   W = w;
  194.   H = h;
  195. }
  196.  
  197. void
  198. mouse(int button, int state, int x, int y)
  199. {
  200.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  201.     spinning = 0;
  202.     glutIdleFunc(NULL);
  203.     moving = 1;
  204.     beginx = x;
  205.     beginy = y;
  206.     if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
  207.       scaling = 1;
  208.     } else {
  209.       scaling = 0;
  210.     }
  211.   }
  212.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  213.     moving = 0;
  214.   }
  215. }
  216.  
  217. void
  218. animate(void)
  219. {
  220.   add_quats(lastquat, curquat, curquat);
  221.   newModel = 1;
  222.   glutPostRedisplay();
  223. }
  224.  
  225. void
  226. motion(int x, int y)
  227. {
  228.   if (scaling) {
  229.     scalefactor = scalefactor * (1.0 + (((float) (beginy - y)) / H));
  230.     beginx = x;
  231.     beginy = y;
  232.     newModel = 1;
  233.     glutPostRedisplay();
  234.     return;
  235.   }
  236.   if (moving) {
  237.     trackball(lastquat,
  238.       (2.0*beginx - W) / W,
  239.       (H - 2.0*beginy) / H,
  240.       (2.0*x - W) / W,
  241.       (H - 2.0*y) / H
  242.       );
  243.     beginx = x;
  244.     beginy = y;
  245.     spinning = 1;
  246.     glutIdleFunc(animate);
  247.   }
  248. }
  249.  
  250. GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
  251.  
  252. void
  253. controlLights(int value)
  254. {
  255.   switch (value) {
  256.   case 1:
  257.     lightZeroSwitch = !lightZeroSwitch;
  258.     if (lightZeroSwitch) {
  259.       glEnable(GL_LIGHT0);
  260.     } else {
  261.       glDisable(GL_LIGHT0);
  262.     }
  263.     break;
  264.   case 2:
  265.     lightOneSwitch = !lightOneSwitch;
  266.     if (lightOneSwitch) {
  267.       glEnable(GL_LIGHT1);
  268.     } else {
  269.       glDisable(GL_LIGHT1);
  270.     }
  271.     break;
  272. #ifdef GL_MULTISAMPLE_SGIS
  273.   case 3:
  274.     if(glIsEnabled(GL_MULTISAMPLE_SGIS)) {
  275.       glDisable(GL_MULTISAMPLE_SGIS);
  276.     } else {
  277.       glEnable(GL_MULTISAMPLE_SGIS);
  278.     }
  279.     break;
  280. #endif
  281.   case 4:
  282.     glutFullScreen();
  283.     break;
  284.   case 5:
  285.     exit(0);
  286.     break;
  287.   }
  288.   glutPostRedisplay();
  289. }
  290.  
  291. void
  292. vis(int visible)
  293. {
  294.   if (visible == GLUT_VISIBLE) {
  295.     if (spinning)
  296.       glutIdleFunc(animate);
  297.   } else {
  298.     if (spinning)
  299.       glutIdleFunc(NULL);
  300.   }
  301. }
  302.  
  303. int
  304. main(int argc, char **argv)
  305. {
  306.   glutInit(&argc, argv);
  307.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  308.   trackball(curquat, 0.0, 0.0, 0.0, 0.0);
  309.   glutCreateWindow("dinospin");
  310.   glutDisplayFunc(redraw);
  311.   glutReshapeFunc(myReshape);
  312.   glutVisibilityFunc(vis);
  313.   glutMouseFunc(mouse);
  314.   glutMotionFunc(motion);
  315.   glutCreateMenu(controlLights);
  316.   glutAddMenuEntry("Toggle right light", 1);
  317.   glutAddMenuEntry("Toggle left light", 2);
  318.   if(glutGet(GLUT_WINDOW_NUM_SAMPLES) > 0) {
  319.       glutAddMenuEntry("Toggle multisampling", 3);
  320.       glutSetWindowTitle("dinospin (multisample capable)");
  321.   }
  322.   glutAddMenuEntry("Full screen", 4);
  323.   glutAddMenuEntry("Quit", 5);
  324.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  325.   makeDinosaur();
  326.   glEnable(GL_CULL_FACE);
  327.   glEnable(GL_DEPTH_TEST);
  328.   glEnable(GL_LIGHTING);
  329.   glMatrixMode(GL_PROJECTION);
  330.   gluPerspective( /* field of view in degree */ 40.0,  /* aspect 
  331.                                                           ratio 
  332.                                                         */ 1.0,
  333.     /* Z near */ 1.0, /* Z far */ 40.0);
  334.   glMatrixMode(GL_MODELVIEW);
  335.   gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
  336.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  337.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  338.   glPushMatrix();       /* dummy push so we can pop on model
  339.                            recalc */
  340.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  341.   glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  342.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  343.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  344.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  345.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  346.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  347.   glEnable(GL_LIGHT0);
  348.   glEnable(GL_LIGHT1);
  349.   glLineWidth(2.0);
  350.   glutMainLoop();
  351.   return 0;             /* ANSI C requires main to return int. */
  352. }
  353.